<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Begin Jekyll SEO tag v2.7.1 -->
<title>List | 微光</title>
<meta name="generator" content="Jekyll v4.2.1">
<meta property="og:title" content="List">
<meta property="og:locale" content="en_US">
<meta name="description" content="要解释 list 数据类型，最好的方式是先从一点点点点理论开始，因为 list 这个词经常被 IT 技术人员以不恰当的方式使用。比如，Python 中 list 并不像我们想象的那样（比如链表），而是指数组（比如 Ruby 中的那种数组）。">
<meta property="og:description" content="要解释 list 数据类型，最好的方式是先从一点点点点理论开始，因为 list 这个词经常被 IT 技术人员以不恰当的方式使用。比如，Python 中 list 并不像我们想象的那样（比如链表），而是指数组（比如 Ruby 中的那种数组）。">
<link rel="canonical" href="/redis/data-type/list.html">
<meta property="og:url" content="/redis/data-type/list.html">
<meta property="og:site_name" content="微光">
<meta property="og:type" content="article">
<meta property="article:published_time" content="2022-01-18T01:52:04+08:00">
<meta name="twitter:card" content="summary">
<meta property="twitter:title" content="List">
<script type="application/ld+json">
{"description":"要解释 list 数据类型，最好的方式是先从一点点点点理论开始，因为 list 这个词经常被 IT 技术人员以不恰当的方式使用。比如，Python 中 list 并不像我们想象的那样（比如链表），而是指数组（比如 Ruby 中的那种数组）。","url":"/redis/data-type/list.html","headline":"List","dateModified":"2022-01-18T01:52:04+08:00","datePublished":"2022-01-18T01:52:04+08:00","@type":"BlogPosting","mainEntityOfPage":{"@type":"WebPage","@id":"/redis/data-type/list.html"},"@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
<link rel="stylesheet" href="/assets/css/normalize.css">
  <link rel="stylesheet" href="/assets/css/style.css">
<link type="application/atom+xml" rel="alternate" href="/feed.xml" title="微光">
<script>MathJax={"tex":{"inlineMath":[["$","$"],["\\(","\\)"]],"displayMath":[["$$","$$"],["\\[","\\]"]]},"svg":{"fontCache":"global"}}</script><script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script><script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
</head>
<body>
<header class="site-header">

  <div class="wrapper">
<a class="site-title" rel="author" href="/">微光</a><nav class="site-nav">
        <input type="checkbox" id="nav-trigger" class="nav-trigger">
        <label for="nav-trigger">
          <span class="menu-icon">
            <svg viewbox="0 0 18 15" width="18px" height="15px">
              <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"></path>
            </svg>
          </span>
        </label>

        <div class="trigger">
<a class="page-link" href="/about/">About</a><a class="page-link" href="/doc/main">DocMain</a><a class="page-link" href="/sites.html">Sites</a>
</div>
      </nav>
</div>
</header>
<div class="x-collections-bar">
  <a href="/">Home</a>
  
    
      <a href="/algri/index">算法</a>
    
  
    
      <a href="/java/index">Java</a>
    
  
    
  
    
  
    
      <a href="/redis/index">Redis</a>
    
  
</div>

<div class="x-content-side-layout x-container">
  <div class="x-left">
    <h3>本文目录</h3>
    <ul id="toc" class="section-nav">
<li class="toc-entry toc-h2"><a href="#%E5%BC%80%E5%A7%8B%E4%BD%BF%E7%94%A8-list">开始使用 List</a></li>
<li class="toc-entry toc-h2"><a href="#%E4%BD%BF%E7%94%A8-list-%E7%9A%84%E4%B8%80%E8%88%AC%E5%9C%BA%E6%99%AF">使用 List 的一般场景</a></li>
<li class="toc-entry toc-h2"><a href="#%E5%8A%A0%E7%9B%96%E7%9A%84-listcapped-list">加盖的 List（Capped List）</a></li>
<li class="toc-entry toc-h2"><a href="#list-%E4%B8%8A%E7%9A%84%E9%98%BB%E5%A1%9E%E6%93%8D%E4%BD%9C">List 上的阻塞操作</a></li>
<li class="toc-entry toc-h2"><a href="#%E8%87%AA%E5%8A%A8%E5%88%9B%E5%BB%BA%E5%92%8C%E5%88%A0%E9%99%A4-key">自动创建和删除 key</a></li>
<li class="toc-entry toc-h2"><a href="#%E6%93%8D%E4%BD%9C-list-%E7%9A%84%E5%91%BD%E4%BB%A4">操作 List 的命令</a></li>
</ul>
  </div>
  <div class="x-content">
    <h1><strong>Redis - List</strong></h1>
    <small>2022-01-18 01:52:04 +0800</small>
    
    <article class="x-article"><p>要解释 list 数据类型，最好的方式是先从一点点点点理论开始，因为 list 这个词经常被 IT 技术人员以不恰当的方式使用。比如，Python 中 list 并不像我们想象的那样（比如链表），而是指数组（比如 Ruby 中的那种数组）。</p>

<p>从一般视角上看，list 是只是一个带有顺序关系的元素序列：10、20、1、2、3 就是一个列表。但是使用数组实现的 list 和使用链表来实现的 list，在性质表现上十分不同。</p>

<p>Redis 的 list 是用链表实现的。这意味着，即使你的 list 有几百万个元素，那么往 list 的头部或尾部增加一个元素也只消耗常数时间。</p>

<p>有啥缺点呢？数组实现的 list 可以以常数时间来访问指定索引处的元素，而这样的操作用链表却很慢，时间花费依赖于 list 中的元素总数。</p>

<p>Redis 选择用链表来实现 list，原因是对数据库系统来说，往一个 list 中快速的增加一个元素是至关重要的。Another strong advantage, as you’ll see in a moment, is that Redis Lists can be taken at constant length in constant time.</p>

<p>如果要求能够快速访问一个巨大集合中间的元素非常重要，可以使用另一个数据类型：有序集合（Sorted Set）。这个后面说。</p>

<h2 id="开始使用-list">
<a class="anchor" href="#%E5%BC%80%E5%A7%8B%E4%BD%BF%E7%94%A8-list" aria-hidden="true"><span class="octicon octicon-link"></span></a>开始使用 List</h2>

<p>命令 <code class="language-plaintext highlighter-rouge">LPUSH</code> 把一个元素加到 list 的左边（即开头），<code class="language-plaintext highlighter-rouge">RPUSH</code> 把一个元素加到 list 的右边（即末尾）。命令 <code class="language-plaintext highlighter-rouge">LRANGE</code> 从 list 中查出指定索引范围内的数据：</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">&gt;</span><span class="w"> </span>rpush mylist A
<span class="go">(integer) 1
</span><span class="gp">&gt;</span><span class="w"> </span>rpush mylist B
<span class="go">(integer) 2
</span><span class="gp">&gt;</span><span class="w"> </span>lpush mylist first
<span class="go">(integer) 3
</span><span class="gp">&gt;</span><span class="w"> </span>lrange mylist 0 <span class="nt">-1</span>
<span class="go">1) "first"
2) "A"
3) "B"
</span></code></pre></div></div>

<p>注意，<code class="language-plaintext highlighter-rouge">LRANGE</code> 命令接受两个索引，指向范围内要返回的第一个和最后一个元素。它们可以是负值，告诉 redis 从后面开始数，所以 -1 是最后一个元素，-2 是倒数第二个元素，等等等。</p>

<p><code class="language-plaintext highlighter-rouge">LPUSH</code> 和 <code class="language-plaintext highlighter-rouge">RPUSH</code> 都可以接受参数，这样就可以在一个命令里向 list 中 push 多个元素：</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">&gt;</span><span class="w"> </span>rpush mylist 1 2 3 4 5 <span class="s2">"foo bar"</span>
<span class="go">(integer) 9
</span><span class="gp">&gt;</span><span class="w"> </span>lrange mylist 0 <span class="nt">-1</span>
<span class="go">1) "first"
2) "A"
3) "B"
4) "1"
5) "2"
6) "3"
7) "4"
8) "5"
9) "foo bar"
</span></code></pre></div></div>

<p>Redis list 中另一个重要操作是弹出（pop）元素。弹出一个元素的意思是从 list 中得到这个元素，并同时把它从 list 中删除。你可以从左边或者右边弹出元素（对应的命令是 <code class="language-plaintext highlighter-rouge">LPOP</code> 和 <code class="language-plaintext highlighter-rouge">RPOP</code>），类似于你向 list 的左边或者右边推元素：</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">&gt;</span><span class="w"> </span>rpush mylist a b c
<span class="go">(integer) 3
</span><span class="gp">&gt;</span><span class="w"> </span>rpop mylist
<span class="go">"c"
</span><span class="gp">&gt;</span><span class="w"> </span>rpop mylist
<span class="go">"b"
</span><span class="gp">&gt;</span><span class="w"> </span>rpop mylist
<span class="go">"a"
</span></code></pre></div></div>

<p>上例中我们向 list 中添加了 3 个元素，然后把它们弹出，所以最后 list 就空了，没有元素可以弹出了。如果我们从空列表弹出一个元素，那么我们会得到这样的结果：</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">&gt;</span><span class="w"> </span>rpop mylist
<span class="go">(nil)
</span></code></pre></div></div>

<p>即如果没有元素可以返回的话，就返回一个 <code class="language-plaintext highlighter-rouge">NULL</code> value。</p>

<h2 id="使用-list-的一般场景">
<a class="anchor" href="#%E4%BD%BF%E7%94%A8-list-%E7%9A%84%E4%B8%80%E8%88%AC%E5%9C%BA%E6%99%AF" aria-hidden="true"><span class="octicon octicon-link"></span></a>使用 List 的一般场景</h2>

<p>List 在很多任务中都很有用，下面有两个非常有代表性的使用场景：</p>

<ul>
  <li>记住用户在社交网络上发布的最新更新</li>
  <li>进程之间通过生产者-消费者模式进行交流，其中生产者 push 元素到 list 中，消费者（通常是一个 worker）从 list 中消费元素并执行对应的动作。Redis 甚至还有专用的命令来使这种场景既可靠又有效率。</li>
</ul>

<p>比如，Ruby 库 <a href="https://github.com/resque/resque">resque</a> 和 sidekiq 就使用 Redis list 来实现后台任务；<a href="https://www.infoq.com/presentations/Real-Time-Delivery-Twitter/">Twitter 把用户发挥的最新动态推到 Redis list 中</a>。</p>

<p>为了一步步描述一个常见场景，可以想象你的主页展示最新发布的照片到一个共享社交网络，并且你希望可以快速访问到。</p>

<ul>
  <li>每当用户发布一张新照片，我们就把照片 ID <code class="language-plaintext highlighter-rouge">LPUSH</code> 到一个 list 中</li>
  <li>每当用户访问这个主页是，我们使用 <code class="language-plaintext highlighter-rouge">LRANGE 0 9</code> 来获取最近 10 条发布内容</li>
</ul>

<h2 id="加盖的-listcapped-list">
<a class="anchor" href="#%E5%8A%A0%E7%9B%96%E7%9A%84-listcapped-list" aria-hidden="true"><span class="octicon octicon-link"></span></a>加盖的 List（Capped List）</h2>

<p>在很多使用场景中，我们只想使用 list 来存储最近的内容，而不关系他们是什么：社交网络更新、日志或者其他的东西。</p>

<p>Redis 允许我们把 list 用作加盖的集合，通过 <code class="language-plaintext highlighter-rouge">LTRIM</code> 命令，就可以做到仅记住最近 N 个元素，并把其他过早的元素都丢掉。</p>

<p><code class="language-plaintext highlighter-rouge">LTRIM</code> 命令类似于 <code class="language-plaintext highlighter-rouge">LRANGE</code>，不过它不是显示指定范围内的元素，而是把这个范围内的元素用做列表的新值，不在范围内的数据都会被扔掉。</p>

<p>下面的例子说的比较清楚：</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">&gt;</span><span class="w"> </span>rpush mylist 1 2 3 4 5
<span class="go">(integer) 5
</span><span class="gp">&gt;</span><span class="w"> </span>ltrim mylist 0 2
<span class="go">OK
</span><span class="gp">&gt;</span><span class="w"> </span>lrange mylist 0 <span class="nt">-1</span>
<span class="go">1) "1"
2) "2"
3) "3"
</span></code></pre></div></div>

<p>上面的 <code class="language-plaintext highlighter-rouge">LTRIM</code> 命令告诉 Redis 只留下索引值从 0 到 2 的元素，其他的元素都会被丢掉。这就允许实现一个简单但是很有用的的模式：list push 操作和一个 trim 操作一起执行，以实现增加一个元素的同时，把超过限制数量的元素丢掉。</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>LPUSH mylist &lt;some element&gt;
LTRIM mylist 0 999
</code></pre></div></div>

<p>上面的嘴和把一个元素加到 list 中，并只留下最近 1000 个元素。通过 <code class="language-plaintext highlighter-rouge">LRANGE</code> 命令，你就可以访问最新的这些元素，而不用记住非常老的数据。</p>

<p>注意：尽管 <code class="language-plaintext highlighter-rouge">LRANGE</code> 是一个 $O(n)$ 命令，不过从头部或者尾部访问少量的元素的花费也只是常量时间。</p>

<h2 id="list-上的阻塞操作">
<a class="anchor" href="#list-%E4%B8%8A%E7%9A%84%E9%98%BB%E5%A1%9E%E6%93%8D%E4%BD%9C" aria-hidden="true"><span class="octicon octicon-link"></span></a>List 上的阻塞操作</h2>

<p>List 有一个特殊的 feature，使其适合于实现队列，并且通常作为进程间通信系统的构建块：阻塞操作。</p>

<p>想象你想用一个线程往一个 list 中 push 元素，用另一个不同的线程来用这些元素做事情。这就是一个普通的生产者-消费者模型，你可以用下面的简单方法来实现：</p>

<ul>
  <li>生产者用 <code class="language-plaintext highlighter-rouge">LPUSH</code> 来把数据推到 list 中</li>
  <li>消费者用 <code class="language-plaintext highlighter-rouge">RPOP</code> 从 list 中取数据</li>
</ul>

<p>不过可能有时 list 是空的，没有东西可以处理，所以 <code class="language-plaintext highlighter-rouge">RPOP</code> 只是简单返回 <code class="language-plaintext highlighter-rouge">NULL</code>。这种情况下，消费者被迫等待一段时间，之后重试 <code class="language-plaintext highlighter-rouge">RPOP</code> 操作。这个过程叫 <code class="language-plaintext highlighter-rouge">polling</code>，在这个上下文中不够好，因为一些缺点：</p>

<ol>
  <li>强迫 Redis 和客户端执行无用的命令（在空 list 上执行的命令都只是简单的返回 <code class="language-plaintext highlighter-rouge">NULL</code>，没有实际的事情可做）</li>
  <li>因为 worker 得到 <code class="language-plaintext highlighter-rouge">NULL</code> 之后，它就必须等待一段时间，所以就会导致一些延迟。为了使延迟更小，就只能增加 <code class="language-plaintext highlighter-rouge">RPOP</code> 的执行频率，这就又回到了上一条，向 Redis 发出了更多无用调用。</li>
</ol>

<p>所以 Redis 实现了命令 <code class="language-plaintext highlighter-rouge">BLPOP</code> 和 <code class="language-plaintext highlighter-rouge">BRPOP</code>，它们是 <code class="language-plaintext highlighter-rouge">LPOP</code> 和 <code class="language-plaintext highlighter-rouge">RPOP</code> 的阻塞版，如果 list 是空的，就会阻塞到有新的元素被 push 到列表为止，或者阻塞到用户指定的超时时刻。</p>

<p>这里有一个 worker 中 <code class="language-plaintext highlighter-rouge">BRPOP</code> 调用的例子：</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">&gt;</span><span class="w"> </span>brpop tasks 5
<span class="go">1) "tasks"
2) "do_something"
</span></code></pre></div></div>

<p>它是说：从 list <code class="language-plaintext highlighter-rouge">tasks</code> 中等元素来，如果 5 秒内没有元素来就返回。</p>

<p>注意，你可以使用 0 作为超时时间来一直等下去，你甚至可以指定多个 list 以同时在多个 list 上等，其中一个 list 接到元素是就会通知。</p>

<p>关于 <code class="language-plaintext highlighter-rouge">BRPOP</code> 还需要指出：</p>

<ol>
  <li>客户端是按 FIFO 顺序被服务的：即先被阻塞等待的客户端先得到推送来的元素</li>
  <li>它的返回值和 <code class="language-plaintext highlighter-rouge">RPOP</code> 不同：返回一个 2 元素数组，第一个元素是 key 的名字，第二个是得到的元素。因为 <code class="language-plaintext highlighter-rouge">BLPOP</code> 和 <code class="language-plaintext highlighter-rouge">BRPOP</code> 可以同时从多个 list 上阻塞等到元素。</li>
  <li>如果超时，则返回 <code class="language-plaintext highlighter-rouge">NULL</code>
</li>
</ol>

<p>关于 list 和阻塞操作还有一些事情需要你了解，我们建议你从下面来了解更多信息：</p>

<ul>
  <li>使用 <code class="language-plaintext highlighter-rouge">LMOVE</code> 来构建 safer queues 或者 rotating queue 是可能的</li>
  <li>它有一个阻塞版本的命令，叫 <code class="language-plaintext highlighter-rouge">BLMOVE</code>
</li>
</ul>

<h2 id="自动创建和删除-key">
<a class="anchor" href="#%E8%87%AA%E5%8A%A8%E5%88%9B%E5%BB%BA%E5%92%8C%E5%88%A0%E9%99%A4-key" aria-hidden="true"><span class="octicon octicon-link"></span></a>自动创建和删除 key</h2>

<p>以上里例子中，我们都没有在 push 元素前先创建空 list，或者在 list 为空时删除 list。这些都是由 redis 负责的工作，我们在往里添加或者弹出元素时不必关心 list 是否存在。</p>

<p>这不是针对 list 的，而是对 redis 中所有的组合了多种元素的数据类型——stream、set、sorted set和hash——都是这样的。</p>

<p>基本上我们可以用三条规则来描述这种行为：</p>

<ol>
  <li>当我们往一个聚合数据类型中添加元素时，如果目标 key 不存在，那么就会在添加之前先创建一个空的聚合数据类型。</li>
  <li>当我们从一个聚合数据类型中移除元素时，如果 value 空了，那么这个 key 就会被自动销毁。Stream 类型是本条规则的唯一例外。</li>
  <li>对一个不存在的 key 调用一个只读命令，比如 <code class="language-plaintext highlighter-rouge">LLEN</code>（它返回 list 长度），或者写命令从中移除元素，得到的结果就像对一个空的聚合类型数据执行此命令得到的结果一样。</li>
</ol>

<p>规则 1 的例子：</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">&gt;</span><span class="w"> </span>del mylist
<span class="go">(integer) 1
</span><span class="gp">&gt;</span><span class="w"> </span>lpush mylist 1 2 3
<span class="go">(integer) 3
</span></code></pre></div></div>

<p>不过我们不能在 key 存在时，执行类型不对应的命令：</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">&gt;</span><span class="w"> </span><span class="nb">set </span>foo bar
<span class="go">OK
</span><span class="gp">&gt;</span><span class="w"> </span>lpush foo 1 2 3
<span class="go">(error) WRONGTYPE Operation against a key holding the wrong kind of value
</span><span class="gp">&gt;</span><span class="w"> </span><span class="nb">type </span>foo
<span class="go">string
</span></code></pre></div></div>

<p>规则 2 的例子：</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">&gt;</span><span class="w"> </span>lpush mylist 1 2 3
<span class="go">(integer) 3
</span><span class="gp">&gt;</span><span class="w"> </span>exists mylist
<span class="go">(integer) 1
</span><span class="gp">&gt;</span><span class="w"> </span>lpop mylist
<span class="go">"3"
</span><span class="gp">&gt;</span><span class="w"> </span>lpop mylist
<span class="go">"2"
</span><span class="gp">&gt;</span><span class="w"> </span>lpop mylist
<span class="go">"1"
</span><span class="gp">&gt;</span><span class="w"> </span>exists mylist
<span class="go">(integer) 0
</span></code></pre></div></div>

<p>在所有元素都被弹出后，key 就不存在了。</p>

<p>规则 3 的例子：</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">&gt;</span><span class="w"> </span>del mylist
<span class="go">(integer) 0
</span><span class="gp">&gt;</span><span class="w"> </span>llen mylist
<span class="go">(integer) 0
</span><span class="gp">&gt;</span><span class="w"> </span>lpop mylist
<span class="go">(nil)
</span></code></pre></div></div>

<h2 id="操作-list-的命令">
<a class="anchor" href="#%E6%93%8D%E4%BD%9C-list-%E7%9A%84%E5%91%BD%E4%BB%A4" aria-hidden="true"><span class="octicon octicon-link"></span></a>操作 List 的命令</h2>

<ul>
  <li>
<code class="language-plaintext highlighter-rouge">BLMOVE source destination LEFT|RIGHT LEFT|RIGHT timeout</code><br>
 <small>从 list 中弹出第一个元素，然后 push 到另一个 list 中，最后返回这个元素的 value。如果 list 中不存在元素，那么旧阻塞到有元素存在为止。</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">BLMPOP timeout numkeys key [key ...] LEFT|RIGHT [COUNT count]</code><br>
 <small>从 list 中弹出第一个元素。如果 list 中不存在元素，那么就阻塞到有元素存在为止。</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">BLPOP key [key ...] timeout</code><br>
 <small>从 list 中弹出第一个元素，并返回。如果 list 中不存在元素，那么就阻塞到有元素存在为止。</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">BRPOP key [key ...] timeout</code><br>
 <small>从 list 中弹出最后一个元素，并返回。如果 list 中不存在元素，那么就阻塞到有元素存在为止。</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">BRPOPLPUSH source destination timeout</code><br>
 <small>Pop an element from a list, push it to another list and return it; or block until one is available</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LINDEX key index</code><br>
 <small>Get an element from a list by its index</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LINSERT key BEFORE|AFTER pivot element</code><br>
 <small>Insert an element before or after another element in a list</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LLEN key</code><br>
 <small>Get the length of a list</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LMOVE source destination LEFT|RIGHT LEFT|RIGHT</code><br>
 <small>Pop an element from a list, push it to another list and return it</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LMPOP numkeys key [key ...] LEFT|RIGHT [COUNT count]</code><br>
 <small>Pop elements from a list</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LPOP key [count]</code><br>
 <small>Remove and get the first elements in a list</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LPOS key element [RANK rank] [COUNT num-matches] [MAXLEN len]</code><br>
 <small>Return the index of matching elements on a list</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LPUSH key element [element ...]</code><br>
 <small>Prepend one or multiple elements to a list</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LPUSHX key element [element ...]</code><br>
 <small>Prepend an element to a list, only if the list exists</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LRANGE key start stop</code><br>
 <small>Get a range of elements from a list</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LREM key count element</code><br>
 <small>Remove elements from a list</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LSET key index element</code><br>
 <small>Set the value of an element in a list by its index</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">LTRIM key start stop</code><br>
 <small>Trim a list to the specified range</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">RPOP key [count]</code><br>
 <small>Remove and get the last elements in a list</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">RPOPLPUSH source destination</code><br>
 <small>Remove the last element in a list, prepend it to another list and return it</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">RPUSH key element [element ...]</code><br>
 <small>Append one or multiple elements to a list</small>
</li>
  <li>
<code class="language-plaintext highlighter-rouge">RPUSHX key element [element ...]</code><br>
 <small>Append an element to a list, only if the list exists</small>
</li>
</ul>
</article>
  </div>
  <div class="x-right">
    <h3>Redis</h3>
    
      <div class="x-collection-section">
        <h4>开始</h4>
        
        <ol>
          
            
              <li><a href="/redis/index.html">开始</a></li>
            
          
            
              <li><a href="/redis/install.html">安装</a></li>
            
          
            
              <li><a href="/redis/concept.html">相关概念预览</a></li>
            
          
        </ol>
      </div>
    
      <div class="x-collection-section">
        <h4>数据类型</h4>
        
        <ol>
          
            
              <li><a href="/redis/data-type/key-and-string.html">Key 和 String</a></li>
            
          
            
              <li class="active"><a href="/redis/data-type/list.html">List</a></li>
            
          
            
              <li><a href="/redis/data-type/hash.html">Hash</a></li>
            
          
            
              <li><a href="/redis/data-type/set.html">Set</a></li>
            
          
            
              <li><a href="/redis/data-type/zset.html">Sorted Set</a></li>
            
          
            
              <li><a href="/redis/data-type/bitmap.html">Bitmap</a></li>
            
          
            
              <li><a href="/redis/data-type/hyperloglog.html">Hyperloglog</a></li>
            
          
            
              <li><a href="/redis/data-type/geo.html">Geo</a></li>
            
          
        </ol>
      </div>
    
      <div class="x-collection-section">
        <h4>其他特性</h4>
        
        <ol>
          
            
              <li><a href="/redis/feature/pipeline.html">流水线处理</a></li>
            
          
        </ol>
      </div>
    
      <div class="x-collection-section">
        <h4>持久化</h4>
        
        <ol>
          
            
              <li><a href="/redis/persist/durability.html">持久化在说什么</a></li>
            
          
            
              <li><a href="/redis/persist/rdb.html">快照（Snapshotting）</a></li>
            
          
            
              <li><a href="/redis/persist/aof.html">AOF</a></li>
            
          
        </ol>
      </div>
    
      <div class="x-collection-section">
        <h4>运维</h4>
        
        <ol>
          
            
              <li><a href="/redis/ops/persistence.html">持久化方案</a></li>
            
          
        </ol>
      </div>
    
      <div class="x-collection-section">
        <h4>应用场景</h4>
        
        <ol>
          
            
              <li><a href="/redis/usecase/blogs.html">应用场景相关文章</a></li>
            
          
        </ol>
      </div>
    
  </div>
</div>
<footer class="site-footer h-card">
  <data class="u-url" href="/"></data>

  <div class="wrapper">

    <div class="footer-col-wrapper">
      <div class="footer-col">
        <p class="feed-subscribe">
          <a href="/feed.xml">
            <svg class="svg-icon orange">
              <use xlink:href="/assets/social-icons.svg#rss"></use>
            </svg><span>Subscribe</span>
          </a>
        </p>
      </div>
      <div class="footer-col">
        <p>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</p>
      </div>
    </div>

    <div class="social-links"></div>

  </div>

</footer>
</body>
</html>
